using SerialTool.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SerialTool.Services;

public class ProtocolService
{
    private static ProtocolService? _instance;
    private ProtocolConfig? _activeProtocol;
    
    // 协议缓冲区及状态
    private readonly List<byte> _receiveBuffer = new();
    private bool _isPacketInProgress = false;
    private DateTime _lastReceiveTime = DateTime.MinValue;
    
    private ProtocolService() { }
    
    public static ProtocolService Instance => _instance ??= new ProtocolService();
    
    // 设置当前活动协议
    public void SetActiveProtocol(ProtocolConfig? protocol)
    {
        _activeProtocol = protocol;
        // 清空缓冲区和状态
        _receiveBuffer.Clear();
        _isPacketInProgress = false;
    }
    
    // 根据协议格式化发送数据
    public byte[] FormatSendData(byte[] rawData)
    {
        if (_activeProtocol == null || !_activeProtocol.IsEnabled)
        {
            return rawData; // 无协议处理
        }
        
        return _activeProtocol.ProtocolType switch
        {
            "Modbus" => FormatModbusData(rawData, (ModbusConfig)_activeProtocol),
            "Custom" => FormatCustomData(rawData, (CustomProtocolConfig)_activeProtocol),
            _ => rawData // 默认无处理
        };
    }
    
    // 处理接收数据
    public byte[]? ProcessReceivedData(byte[] newData)
    {
        if (_activeProtocol == null || !_activeProtocol.IsEnabled)
        {
            return newData; // 无协议处理
        }
        
        // 添加新数据到缓冲区
        _receiveBuffer.AddRange(newData);
        _lastReceiveTime = DateTime.Now;
        
        return _activeProtocol.ProtocolType switch
        {
            "Modbus" => ProcessModbusData((ModbusConfig)_activeProtocol),
            "Custom" => ProcessCustomData((CustomProtocolConfig)_activeProtocol),
            _ => newData // 默认直接返回接收到的数据
        };
    }
    
    // 检查数据包超时
    public bool CheckTimeout(int timeoutMs)
    {
        if (!_isPacketInProgress || _receiveBuffer.Count == 0)
            return false;
            
        return (DateTime.Now - _lastReceiveTime).TotalMilliseconds > timeoutMs;
    }
    
    // 处理超时
    public byte[]? HandleTimeout()
    {
        if (_receiveBuffer.Count == 0)
            return null;
            
        var result = _receiveBuffer.ToArray();
        _receiveBuffer.Clear();
        _isPacketInProgress = false;
        return result;
    }
    
    // ==================== Modbus 协议处理 =====================
    
    private byte[] FormatModbusData(byte[] rawData, ModbusConfig config)
    {
        // 基本实现：添加从站地址和CRC校验
        var result = new List<byte>(rawData.Length + 3);
        
        // 添加从站地址
        result.Add(config.SlaveAddress);
        
        // 添加原始数据
        result.AddRange(rawData);
        
        // 如果是RTU模式，添加CRC校验
        if (config.Mode == ModbusConfig.ModbusMode.RTU && config.UseCRC)
        {
            ushort crc = CalculateModbusCRC(result.ToArray());
            result.Add((byte)(crc & 0xFF));         // CRC低字节
            result.Add((byte)((crc >> 8) & 0xFF));  // CRC高字节
        }
        
        return result.ToArray();
    }
    
    private byte[]? ProcessModbusData(ModbusConfig config)
    {
        // 简化处理：检查是否有足够的数据构成一个Modbus响应
        // 实际实现需要根据Modbus功能码判断帧长度
        
        // 最小长度：从站地址(1) + 功能码(1) + 数据(n) + CRC(2)
        if (_receiveBuffer.Count < 4)
        {
            _isPacketInProgress = true;
            return null; // 数据不完整
        }
        
        // 验证从站地址
        if (_receiveBuffer[0] != config.SlaveAddress)
        {
            // 地址不匹配，清理缓冲区
            _receiveBuffer.Clear();
            _isPacketInProgress = false;
            return Array.Empty<byte>();
        }
        
        // 暂时返回完整数据，实际实现应检查功能码和长度
        var result = _receiveBuffer.ToArray();
        _receiveBuffer.Clear();
        _isPacketInProgress = false;
        return result;
    }
    
    private ushort CalculateModbusCRC(byte[] data)
    {
        ushort crc = 0xFFFF;
        
        foreach (byte b in data)
        {
            crc ^= b;
            for (int i = 0; i < 8; i++)
            {
                if ((crc & 0x0001) != 0)
                {
                    crc >>= 1;
                    crc ^= 0xA001;
                }
                else
                {
                    crc >>= 1;
                }
            }
        }
        
        return crc;
    }
    
    // =================== 自定义协议处理 ======================
    
    private byte[] FormatCustomData(byte[] rawData, CustomProtocolConfig config)
    {
        var result = new List<byte>();
        
        // 添加起始分隔符
        if (!string.IsNullOrEmpty(config.StartDelimiter))
        {
            result.AddRange(Encoding.ASCII.GetBytes(config.StartDelimiter));
        }
        
        // 添加数据
        result.AddRange(rawData);
        
        // 添加校验和
        if (config.UseChecksum)
        {
            byte checksum = CalculateChecksum(rawData, config.Method);
            result.Add(checksum);
        }
        
        // 添加结束分隔符
        if (!string.IsNullOrEmpty(config.EndDelimiter))
        {
            result.AddRange(Encoding.ASCII.GetBytes(config.EndDelimiter));
        }
        
        return result.ToArray();
    }
    
    private byte[]? ProcessCustomData(CustomProtocolConfig config)
    {
        byte[] startBytes = Array.Empty<byte>();
        
        // 检查是否有起始分隔符
        if (!string.IsNullOrEmpty(config.StartDelimiter))
        {
            startBytes = Encoding.ASCII.GetBytes(config.StartDelimiter);
            if (_receiveBuffer.Count < startBytes.Length)
            {
                _isPacketInProgress = true;
                return null; // 等待更多数据
            }
            
            // 查找起始分隔符
            int startIndex = FindSequence(_receiveBuffer, startBytes);
            if (startIndex == -1)
            {
                _isPacketInProgress = true;
                return null; // 未找到起始分隔符
            }
            
            // 移除起始分隔符前的数据
            if (startIndex > 0)
            {
                _receiveBuffer.RemoveRange(0, startIndex);
            }
        }
        
        // 检查结束分隔符
        if (!string.IsNullOrEmpty(config.EndDelimiter))
        {
            byte[] endBytes = Encoding.ASCII.GetBytes(config.EndDelimiter);
            int endIndex = FindSequence(_receiveBuffer, endBytes, startBytes.Length);
            
            if (endIndex == -1)
            {
                _isPacketInProgress = true;
                return null; // 未找到结束分隔符
            }
            
            // 提取数据
            int dataLength = endIndex - startBytes.Length;
            byte[] data = _receiveBuffer.Skip(startBytes.Length).Take(dataLength).ToArray();
            
            // 验证校验和
            if (config.UseChecksum && dataLength > 0)
            {
                byte expectedChecksum = data[dataLength - 1];
                byte[] dataWithoutChecksum = data.Take(dataLength - 1).ToArray();
                byte calculatedChecksum = CalculateChecksum(dataWithoutChecksum, config.Method);
                
                if (expectedChecksum != calculatedChecksum)
                {
                    // 校验和错误，清理缓冲区
                    _receiveBuffer.RemoveRange(0, endIndex + endBytes.Length);
                    _isPacketInProgress = false;
                    return Array.Empty<byte>();
                }
                
                // 返回不包含校验和的数据
                _receiveBuffer.RemoveRange(0, endIndex + endBytes.Length);
                _isPacketInProgress = false;
                return dataWithoutChecksum;
            }
            
            // 返回数据
            _receiveBuffer.RemoveRange(0, endIndex + endBytes.Length);
            _isPacketInProgress = false;
            return data;
        }
        else
        {
            // 没有结束分隔符，暂时返回所有数据
            byte[] data = _receiveBuffer.ToArray();
            _receiveBuffer.Clear();
            _isPacketInProgress = false;
            return data;
        }
    }
    
    private int FindSequence(List<byte> buffer, byte[] sequence, int startIndex = 0)
    {
        if (buffer.Count < sequence.Length + startIndex)
            return -1;
            
        for (int i = startIndex; i <= buffer.Count - sequence.Length; i++)
        {
            bool found = true;
            for (int j = 0; j < sequence.Length; j++)
            {
                if (buffer[i + j] != sequence[j])
                {
                    found = false;
                    break;
                }
            }
            
            if (found)
                return i;
        }
        
        return -1;
    }
    
    private byte CalculateChecksum(byte[] data, CustomProtocolConfig.ChecksumMethod method)
    {
        return method switch
        {
            CustomProtocolConfig.ChecksumMethod.Sum => (byte)data.Sum(b => b),
            CustomProtocolConfig.ChecksumMethod.XOR => data.Aggregate((byte)0, (x, y) => (byte)(x ^ y)),
            CustomProtocolConfig.ChecksumMethod.CRC16 => (byte)(CalculateModbusCRC(data) & 0xFF),
            _ => 0
        };
    }
} 